package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.StageLogHelp;
import com.xbongbong.paas.service.PublicGroupSyncService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.listbatch.pojo.dto.ListBatchDTO;
import com.xbongbong.pro.message.constant.CluePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.AutoClueAssignmentRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.pojo.dto.PublicGroupRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.opportunity.pojo.JudgeStageChangedPojo;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueStageLogEntity;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueStageLogModel;
import com.xbongbong.saas.model.ClueStageModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.service.AutoClueAssignmentRabbitService;
import com.xbongbong.saas.service.ListBatchService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.help.saas.WorkFlowSaasStageHelp;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
@Slf4j
public class WorkflowClueStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {

    private static final Logger LOG = LoggerFactory.getLogger(WorkflowClueStrategy.class);

    @Resource
    private UserModel userModel;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    @Lazy
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private ClueModel clueModel;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private ListBatchService listBatchService;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private MessageService messageService;
    @Resource
    private AutoClueAssignmentRabbitService autoClueAssignmentRabbitService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private StageLogHelp stageLogHelp;
    @Resource
    private WorkFlowSaasStageHelp workFlowSaasStageHelp;
    @Resource
    private ClueStageLogModel clueStageLogModel;
    @Resource
    private ClueStageModel clueStageModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PublicGroupSyncService publicGroupSyncService;

    @Override
    public List<Integer> type() {
        return Collections.singletonList(XbbRefTypeEnum.CLUE.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        Long formId = pojoData.getFormId();
        User user = workflowTransferPOJO.getUser();
        String creatorId = user.getUserId();
        UserEntity creator = userModel.getByKeyIngoreDel(creatorId, corpid);

        // 文件柜保存
        saveDataCabinetFile(workflowTransferPOJO);

        try {
            List<String> clueUserIdList = clueUserModel.getClueUserIdList(corpid, dataId, BasicConstant.ONE);
            Integer operate = workflowTransferPOJO.getOperate();
            Integer isPublic = data.getInteger(ClueEnum.IS_PUBLIC.getAttr());
            if (!(Objects.equals(operate, WorkflowOperateEnum.ADD.getType()) && Objects.equals(isPublic, BasicConstant.ONE)) && CollectionsUtil.isEmpty(clueUserIdList)) {
                ListBatchDTO listBatchDTO = new ListBatchDTO();
                listBatchDTO.setCorpid(corpid);
                listBatchDTO.setUserId(creatorId);
                listBatchDTO.setLoginUserName(user.getName());
                UserVO userVO = new UserVO();
                BeanUtil.copyProperties(creator, userVO);
                userVO.getPermSet().add(ProPermissionAliasEnum.CLUE_BACK.getAlias());
                listBatchDTO.setLoginUser(userVO);
                listBatchDTO.setDataIdList(Collections.singletonList(dataId));
                listBatchDTO.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
                listBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                listBatchDTO.setFormId(pojoData.getFormId());
                listBatchDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                // 退回公海池
                listBatchService.backCustomer(listBatchDTO);
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowClueStrategy.save listBatchService.backCustomer error", e);
        }
        // 线索自动同步
        Integer isPublic = getIntegerOrDefaultFromFormData(data, ClueEnum.IS_PUBLIC.getAttr(), 0);
        if (Objects.equals(isPublic, 1) && !Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
            AutoClueAssignmentRabbitMqDTO mqDTO = new AutoClueAssignmentRabbitMqDTO(corpid, Collections.singletonList(dataId));
            autoClueAssignmentRabbitService.autoClueAssignment(mqDTO);
        }

        try {
            if (!Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                // 线索创建消息推送
                UserEntity creatorUser = userModel.getByKey(user.getUserId(), corpid);
                String companyName = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.COMPANY_NAME.getAttr(), "");
                ClueEntityExt clueEntityExt = new ClueEntityExt();
                clueEntityExt.setId(dataId);
                List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CLUE_ADD_PUSH.getCode(), PushTypeEnum.CLUE_ADD_PUSH.getSubCode(), creatorUser, clueEntityExt);
                PushRefTypePojo.Options options = new PushRefTypePojo.Options(pojoData.getAppId(), pojoData.getMenuId(), formId, dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), pojoData.getBusinessType(), pojoData.getSubBusinessType());
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(CluePushConstant.CLUE_ADD_TITLE), String.format(I18nMessageUtil.getMessage(CluePushConstant.CLUE_ADD_CONTENT), creatorUser.getName(), companyName), null, options);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, PushTypeEnum.CLUE_ADD_PUSH);
            }
        } catch (Exception e) {
            log.error("线索创建消息推送", e);
        }

        // 新建的时候阶段不为0或者编辑时阶段不一致才需要更改阶段
        String stageCode = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.CLUE_STAGE.getAttr(), "");
        Integer reasonId = getIntegerOrDefaultFromFormData(data, ClueEnum.INVALID_REASON.getAttr(), BasicConstant.ZERO);
        String invalidMemo = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.INVALID_MEMO.getAttr(), "");

        // 新建的时候阶段不为空或者编辑时阶段不一致才需要更改阶段
        try {
            JudgeStageChangedPojo judgeStageChangedPojo = stageLogHelp.judgeStageChanged(corpid, formId, dataId, stageCode, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode());
            if (judgeStageChangedPojo.getIsStageChanged()) {
                workFlowSaasStageHelp.workFlowStageJump(workflowTransferPOJO, ClueEnum.CLUE_STAGE.getAttr(), null);
            }
        } catch (Exception e) {
            LOG.error("新建线索阶段变更", e);
        }

        ClueEntityExt clueEntityExt = clueModel.getByKey(dataId, corpid);
        try {
            //计算评分（线索的编辑和导入时数据的覆盖底层都是走到这里）
            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE,corpid,dataId,clueEntityExt);
        } catch (Exception e) {
            log.error("e{}",e.getMessage());
        }

        try {
            //根据分组规则绑定所属分组
            boolean cluePublicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
            if (cluePublicPoolSeniorModel && !Objects.equals(workflowTransferPOJO.getIsImport(), 1)) {
                PublicGroupRabbitMqDTO mqDTO = new PublicGroupRabbitMqDTO(corpid, Collections.singletonList(dataId), formId, XbbRefTypeEnum.CLUE.getCode());
                publicGroupSyncService.bindPublicGroupByMq(mqDTO);
            }
        } catch (Exception e) {
            log.error("分组规则绑定所属分组失败{}",e.getMessage());
        }

        // 统计市场活动
        marketActivityForStaticHelp.addMarketActivity(clueEntityExt, XbbRefTypeEnum.CLUE);
        addLinkDataDynamic(workflowTransferPOJO);

        // api
        apiHook(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();
        Long formId = pojoData.getFormId();
        User user = workflowTransferPOJO.getUser();

        String creatorId = user.getUserId();
        UserEntity creator = userModel.getByKeyIngoreDel(creatorId, corpid);


        WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);
        JSONObject oldData = workflowBackupDataEntity.getData();

        // 文件柜保存
        saveDataCabinetFile(workflowTransferPOJO);

//        if (Objects.isNull(saasFormSaveDTO.getOwnerId()) || (Objects.nonNull(saasFormSaveDTO.getOwnerId()) && saasFormSaveDTO.getOwnerId().isEmpty())) {
//            saasFormSaveDTO.setSubBusinessType(XbbRefTypeEnum.CLUE_PUBLIC.getCode());
//        }

        try {
            List<String> clueUserIdList = clueUserModel.getClueUserIdList(corpid, dataId, BasicConstant.ONE);
            if (CollectionsUtil.isEmpty(clueUserIdList)) {
                if (Objects.nonNull(workflowBackupDataEntity)) {
                    // 工作流退回公海池团队数据特殊操作，因为在工作流内团队数据实时更新，已经没有前负责人的数据，需要再生成一份数据
                    JSONObject backupData = workflowBackupDataEntity.getData();
                    JSONArray jsonArray = backupData.getJSONArray(StringConstant.USER_TEAM);
                    List<ClueUserEntity> userEntities = JSON.parseArray(jsonArray.toJSONString(), ClueUserEntity.class);
                    userEntities.forEach(v -> v.setId(null));
                    clueUserModel.insertBatch(userEntities);
                }

                ListBatchDTO listBatchDTO = new ListBatchDTO();
                listBatchDTO.setCorpid(corpid);
                listBatchDTO.setUserId(creatorId);
                listBatchDTO.setLoginUserName(user.getName());
                UserVO userVO = new UserVO();
                BeanUtil.copyProperties(creator, userVO);
                userVO.getPermSet().add(ProPermissionAliasEnum.CLUE_BACK.getAlias());
                listBatchDTO.setLoginUser(userVO);
                listBatchDTO.setDataIdList(Collections.singletonList(dataId));
                listBatchDTO.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
                listBatchDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
                listBatchDTO.setFormId(pojoData.getFormId());
                listBatchDTO.setPlatform(PlatFormEnum.INTERNAL.getValue());
                // 退回公海池
                listBatchService.backCustomer(listBatchDTO);
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowClueStrategy.update listBatchService.backCustomer error", e);
        }



        String stageCode = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.CLUE_STAGE.getAttr(), "");
        Integer reasonId = getIntegerOrDefaultFromFormData(data, ClueEnum.INVALID_REASON.getAttr(), BasicConstant.ZERO);
        String invalidMemo = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.INVALID_MEMO.getAttr(), "");

        // 新建的时候阶段不为空或者编辑时阶段不一致才需要更改阶段
        JudgeStageChangedPojo judgeStageChangedPojo = stageLogHelp.judgeStageChanged(corpid, formId, dataId, stageCode, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode());
        if (judgeStageChangedPojo.getIsStageChanged()) {
            try {
                //跳转前的阶段需要从log表中实时去查一下，工作流的流转数据已经被更新过了，不能从那里拿
                ClueStageLogEntity clueStageLogEntity = clueStageLogModel.getIsNowStage(corpid, formId, dataId);
                PaasStageEntity clueStageEntity = null;
                if ( !Objects.isNull(clueStageLogEntity)) {
                    Long stageId = clueStageLogEntity.getStageId();
                    clueStageEntity = clueStageModel.getByKey(stageId, corpid);
                }

                workFlowSaasStageHelp.workFlowStageJump(workflowTransferPOJO, ClueEnum.CLUE_STAGE.getAttr(), clueStageEntity);
            } catch (Exception e) {
                log.error("线索阶段变更消息推送", e);
            }
        }

        try {
            // 计算评分（线索的编辑和导入时数据的覆盖底层都是走到这里）
            ClueEntityExt clueEntityExt = clueModel.getByKey(dataId, corpid);
            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE,corpid,dataId, clueEntityExt);

            // 统计市场活动
            marketActivityForStaticHelp.updateMarketActivity(clueEntityExt, RedundantTemplateTypeEnum.CLUE);
        } catch (Exception e) {
            log.error("e{}",e.getMessage());
        }
        // log
        afterUpdateLog(workflowTransferPOJO);
    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId, corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                ClueEntityExt clueEntityExt = new ClueEntityExt();
                clueEntityExt.setId(dataId);
                clueEntityExt.setCorpid(corpid);
                clueEntityExt.setData(data);
                clueEntityExt.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                // 获取负责人
                clueEntityExt.setOwnerId(getOwnerId(data));
                clueEntityExt.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));
                List<ClueUserEntity> clueUserList = JSON.parseArray(data.getString(StringConstant.USER_TEAM), ClueUserEntity.class);

                FormDataUtil.removeSystemData(data);
                data.remove(StringConstant.USER_TEAM);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    clueEntityExt.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                clueModel.update(clueEntityExt);
                // 回退被删掉的子表单
                updateBackSubForm(clueEntityExt, corpid, IndexTypeEnum.IDX_SAAS_CLUE_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);
                saveUserTeam(clueUserList, corpid, clueEntityExt.getId());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowClueStrategy.updateBack error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            ClueEntityExt clueEntityExt = new ClueEntityExt();
            clueEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                clueEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                clueEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            clueEntityExt.setCorpid(corpid);
            clueEntityExt.setUpdateTime(DateTimeUtil.getInt());
            clueModel.update(clueEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_CLUE_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);

            // 团队
            List<ClueUserEntity> contractUserList = clueUserModel.getClueUserList(corpid, dataId, null);
            if (CollectionsUtil.isNotEmpty(contractUserList)) {
                clueUserModel.deleteBatch(corpid, contractUserList, WriteRequest.RefreshPolicy.NONE, del.getDel());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowClueStrategy.approvalFailed error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void saveUserTeam(List<ClueUserEntity> list, String corpid, Long dataId) throws XbbException {

        try {
            List<ClueUserEntity> bomUserList = clueUserModel.getClueUserList(corpid, dataId, null);
            List<Long> idList = new ArrayList<>();
            list.forEach(item->idList.add(item.getId()));


            bomUserList.removeIf(item->idList.contains(item.getId()));

            if (CollectionsUtil.isNotEmpty(bomUserList)) {
                clueUserModel.deleteBatch(corpid, bomUserList,  WriteRequest.RefreshPolicy.NONE, DelEnum.DELETE.getDel());
            }
            if (CollectionsUtil.isNotEmpty(list)) {
                clueUserModel.updateBatch(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowClueStrategy.saveUserTeam error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
}
